/*
 * HexConverter.c
 *
 *  Created on: Feb 6, 2012
 *      Author: Ivan
 */



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <limits.h>
#include <assert.h>

#define output "Hex.bin"


char *Read_HexFile(char *a);
char *interpilate_String(char *a);
unsigned char * createData(char *a);
unsigned char * CheckData(char *rawhex);
void createBinFile( unsigned char *g,char *f);
unsigned char * CheckFinalData(char *rawhex);

int Checksum(char*a);



/*
 * fseek(f, 0, SEEK_END); // seek to end of file
	size = ftell(f);
 */
int amount;
int zeropoints[50]={};
int size;

int main()
{
	/*hexdump to read*/

	amount =0;
	/*
	system("objcopy -I ihex Hex.hex  -O binary Hex.bin");
	*/
			char *s;
			s=calloc(180,sizeof(char));
		    int length;
		    printf("Input File Name:");
		    scanf("%s", s);
		    char *d=calloc(40,sizeof(char));
		    length = strlen(s);
		    strcat(d,&s[length-3]);
		    /*no idea what the problem is */


		    char *outputfile;
		    outputfile=calloc(40,sizeof(char));

		    outputfile=strncpy( outputfile, s, length-4 );
		    outputfile=strcat(outputfile,".bin");


		    	createBinFile(   createData(  Read_HexFile(s)  ) ,outputfile  );
		    	free(outputfile);
		    	free(s);
	return 0;
}
char * Read_HexFile(char *name)
{
	FILE *fp;

	/* long int pos1, pos2; */
	char  *oneline;
	char *largeline;




	/* Open the file for reading */
	fp = fopen(name, "r");

		fseek(fp, 0, SEEK_END); /* seek to end of file*/
		size = ftell(fp); /*get current file pointer*/
	    fseek(fp, 0, SEEK_SET);

	if( fp )
	{
		largeline=calloc(size*10,sizeof(char));

		char * interprited;
		char *check;
		while(feof(fp)== 0)
		{

			check=calloc(size,sizeof(char));;
			oneline=calloc(size,sizeof(char));
			fscanf(fp,"%s",oneline);

			interprited=interpilate_String(oneline);
			strcpy(check,interprited);
			strcat(largeline,check);

			free(check);
			free(oneline);
			free(interprited);


		}


		fclose(fp);

		return largeline;
	}
	else
	{
			perror("File read error // no such file:");
			exit(10);
	}

}

char * interpilate_String(char *line)
{
	char *bin=calloc(size-2,sizeof(unsigned char));

	int i;
	int length =strlen(line);
	 if(strncmp(line,":",1)==0)
	 {
		 if(line[7]=='0' && line[8]=='0')
		 {
			 /*
		   * Data Record
		   *
		   */
			  i=9;
			  if(Checksum(line) !=0)
			  {
				  perror("Failed Checksum:");
			  }
			  else
			  {

			  }

		 }
		 else if(line[7]=='0' && line[8]=='4')
		 		 {
		 		 /*
		 		   * Extended Linear Address Records (HEX386)
		 		   *
		 		   */
			 	 	 return bin;
		 		 }
		 else if(line[7]=='0' && line[8]=='2')
				 	 {
				 		 /*
				 		   * Extended Segment Address Records (HEX86)
				 		   *
				 		   */
			 return bin;

				 	 }
		 else if(line[7]=='0' && line[8]=='1')
						 	 {
						 		 /*
						 		   * EOF
						 		   *
						 		   */
			 	 	 	 	 	 	 return bin;

						 	 }
		 else if(line[7]=='0' && line[8]=='5')
								 	 {
								 		 /*
								 		   * Start Linear Address Records (MDK-ARM only)
								 		   *
								 		   */

			 	 	 	 	 return bin;
								 	 }






	 }

	while(i<length)
	{
		if(i==length-2)
		{
			return bin;
		}

		else
		{
			char * copy;
			copy=calloc(size,sizeof(char));
			strcpy(copy, &line[i]);

			char *s;
			s=calloc(1,sizeof(char));


			strncpy (s, copy,1 );
			strcat(bin,s);
			i++;
			free(s);
			free(copy);
		}


	}
	return bin;

}


unsigned char * createData(char *rawhex)
{
	unsigned char *x;
	int i=0;
	int j=0;
	unsigned char c,d;
	int length = strlen(rawhex);
	x=calloc(size*10,sizeof(unsigned  char));
	int oper;
	unsigned char final;
	while(i<length)
	{
		/*
		12345678910
		imax=9 =10
		length =10
		imax=8=9
		length =8*/

		oper=0;
		c=rawhex[i];
		d=rawhex[i+1];
		/* take c or with zero right shift 4 bits take resultant and or with d */
		/*syntax
		 * x = y << 4;
		 * 0 | c
		 *
		 *
		 */

		if ('0' <= c && c <= '9')
		{
			if ('0' <= d && d <= '9')
					{


							d = d-'0';


					}
					else if ('A' <= d && d <= 'F')
					{

								d=d-55;

					}

			c = c-'0';

		}
		else if ('A' <= c && c <= 'F')
		{
					if ('0' <= d && d <= '9')
							{

									d = d-'0';


							}
							else if ('A' <= d && d <= 'F')
							{

										d=d-55;

							}
					c=c-55;
		}

		if(c==0 && d==0)
		{
			zeropoints[amount]=j;
			amount++;
			i=i+2;
		}
		else{
				 final =c|oper;
				 final =final<<4;
				 final =d|final;
				 x[j]=final;
				 i=i+2;
				 j++;
		}



	}
	free(rawhex);
	return x;

}

unsigned char * CheckData(char *rawhex)
{
	unsigned char *x;
	/*after colon*/
	int i=1;
	int j=0;
	unsigned char c,d;
	int length = strlen(rawhex);
	x=calloc(size,sizeof(unsigned char));
	int oper;
	unsigned char final;
	while(i<length-2)
	{
		/*
		1234567 8 9 10
		imax=9 =10
		length =10
		imax=8=9
		length =8*/

		oper=0;
		c=rawhex[i];
		d=rawhex[i+1];
		/* take c or with zero right shift 4 bits take resultant and or with d */
		/*syntax
		 * x = y << 4;
		 * 0 | c
		 *
		 *
		 */

		if ('0' <= c && c <= '9')
		{
			if ('0' <= d && d <= '9')
					{


							d = d-'0';


					}
					else if ('A' <= d && d <= 'F')
					{

								d=d-55;

					}

			c = c-'0';

		}
		else if ('A' <= c && c <= 'F')
		{
					if ('0' <= d && d <= '9')
							{

									d = d-'0';


							}
							else if ('A' <= d && d <= 'F')
							{

										d=d-55;

							}
					c=c-55;
		}

		if(c==0 && d==0)
		{
			i=i+2;
		}
		else{
				 final =c|oper;
				 final =final<<4;
				 final =d|final;
				 x[j]=final;
				 i=i+2;
				 j++;
		}



	}
	return x;

}
unsigned char * CheckFinalData(char *rawhex)
{
	unsigned char *x;
	/*after colon*/
	int i=0;
	int j=0;
	unsigned char c,d;
	int length = strlen(rawhex);
	x=calloc(size,sizeof(unsigned char));
	int oper;
	unsigned char final;
	while(i<length)
	{
		/*
		12345678910
		imax=9 =10
		length =10
		imax=8=9
		length =8*/

		oper=0;
		c=rawhex[i];
		d=rawhex[i+1];
		/* take c or with zero right shift 4 bits take resultant and or with d */
		/*syntax
		 * x = y << 4;
		 * 0 | c
		 *
		 *
		 */

		if ('0' <= c && c <= '9')
		{
			if ('0' <= d && d <= '9')
					{


							d = d-'0';


					}
					else if ('A' <= d && d <= 'F')
					{

								d=d-55;

					}

			c = c-'0';

		}
		else if ('A' <= c && c <= 'F')
		{
					if ('0' <= d && d <= '9')
							{

									d = d-'0';


							}
							else if ('A' <= d && d <= 'F')
							{

										d=d-55;

							}
					c=c-55;
		}

		if(c==0 && d==0)
		{
			i=i+2;
		}
		else{
				 final =c|oper;
				 final =final<<4;
				 final =d|final;
				 x[j]=final;
				 i=i+2;
				 j++;
		}



	}
	return x;

}




void createBinFile( unsigned char *h,char *f)
{
  FILE * pFile;
  int j;

  unsigned char * g = h;




  pFile = fopen ( f , "wb" );


  /*
    		j= fwrite (g , 1 , sizeof(g) , pFile );

    */
  /*
    		j=   fputs (g, pFile);
   */
  	  int length= strlen((char*)g);
  	   int i,k;
  	  for (i=0;i<length;i++)
  	  {
  		 for(k=0;k<amount;k++)
  		 {
  			 if(i == zeropoints[k]&&i!=0)
  			 {
  				j=fprintf (pFile,"%c",0);
  			 }

  		 }
  		  j=fprintf (pFile,"%c",g[i]);

  		  if( j < 0 )
    			{
    				perror("File Write Failure!");
    				exit(10);
    			}
  	  }







  fclose (pFile);
}


int Checksum(char * line)
{
	/* :0300300002337A1E
03 + 00 + 30 + 00 + 02 + 33 + 7A = E2, 2's complement is 1E
*/
	/* is it anding or strait adding of the a*/ /* bitwise and or standard addition*/ /* what is the 2's compliment*
	 * cc is the checksum field that represents the checksum of the record.
	 * The checksum is calculated by summing the values of all hexadecimal digit pairs in the record modulo 256 and
	 * taking the two's complement.*/

	/*
	 * A shortcut to manually convert a binary number into its two's complement is to
	 * start at the least significant bit (LSB),
	 * and copy all the zeros (working from LSB toward the most significant bit) until the first 1 is reached;
	 * then copy that 1, and flip all the remaining bits.
	 * This shortcut allows a person to convert a number to its two's complement without
	 * first forming its ones' complement. For example: the two's complement of "0011 1100" is "1100 0100",
	 * where the underlined digits were unchanged by the copying operation (while the rest of the digits were flipped).
	 */

	unsigned char *addition;
	/*
	addition=malloc(size*sizeof(unsigned char));
	*/
	addition=CheckData(line);
	int x=0;
	unsigned char z;
	int i=0;


	/* truncates and doesnt add up*/
	while( i<strlen((char*)addition))
	{
		/*truncate the char value*/
		unsigned char c;
		c=addition[i];
		x = x+ c;
		i++;
	}


	z=(unsigned char)(x%256)-1;

	/*create the negative of x*/


	int length=strlen((char *)line);

	unsigned char *checkline;
	/*
	checkline=malloc(size*sizeof(char));
	*/
	checkline=(unsigned char *)&line[length-2];
	checkline=CheckFinalData((char *)checkline);

	unsigned check=checkline[0];


	/*checks to make sure its the specific one*/
	unsigned compliment = check^0xFF;
	/*for the first line all of them have to equal BF 10111111 191 to and with 40 01000000 64*/
	if(z == compliment)
	{
		free(addition);
		free(checkline);
		return 0;
	}

	else
	{
		free(addition);
		free(checkline);
		return 1;
	}
		/*
		 * what does this mean
		 * x&y&z or ascii x+y+z or x|y|z=checksum beg
		 *
		 * checksum beg%2 if(=0) lsb is 1 else lsb =0
		 * the loop through number until a one is reached
		 * copy 1 then flip remaining bits XOR XFF so 0->1 1->0
		 * then & should get 0
		 *
		 */
	/*
	 * Checksum, two hex digits - the least significant byte of the two's complement of the sum of the values
	 *  of all fields except fields 1 and 6 (Start code ":" byte and two hex digits of the Checksum).
	 *   It is calculated by adding together the hex-encoded bytes (hex digit pairs),
	 *   then leaving only the least significant byte of the result,
	 *   and making a 2's complement (either by subtracting the byte from 0x100,
	 *   or inverting it by XOR-ing with 0xFF and adding 0x01).
	 *   If you are not working with 8-bit variables, you must suppress the overflow by
	 *    AND-ing the result with 0xFF. The overflow may occur since both 0x100-0 and (0x00 XOR 0xFF)+1 equal
	 *     0x100. If the checksum is correctly calculated,
	 *     adding all the bytes (the Byte count, both bytes in Address, the Record type, each Data byte and the Checksum)
	 *      together will always result in a value wherein the least significant byte is zero (0x00).
	 *
		For example, on :0300300002337A1E
			03 + 00 + 30 + 00 + 02 + 33 + 7A = E2, 2's complement is 1E
	 */
}


/* code from other section*/
